home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-11-19 | 19.0 KB | 884 lines | [TEXT/MPS ] |
- /*
- File: PAPSample.cp
-
- Contains: Sample demonstration program for PAP
-
- Copyright: © 1993-1995 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #ifndef __OPENTPTGLOBALNEW__
- #include <OpenTptGlobalNew.h>
- #endif
- #ifndef __OPENTPTAPPLETALK__
- #include <OpenTptAppleTalk.h>
- #endif
- #ifndef __ATALKSAMPLEUTILS__
- #include "ATalkSampleUtils.h"
- #endif
- #ifndef __STDIO__
- #include <stdio.h>
- #endif
- #ifndef __EVENTS__
- #include <Events.h>
- #endif
- #ifndef __TEXTUTILS__
- #include <TextUtils.h>
- #endif
-
- #define byName 1
- #define byAddr 0
-
- const size_t kMaxRecv = 5000; /*Max received data*/
- const size_t kMaxSend = 4096; /*Max send data*/
- UInt8 gIncomingBuffer[kMaxRecv];
-
- #if byName
- TNetbuf gDestName;
- #endif
-
- DDPAddress gDestAddr;
-
- const size_t kMaxReplyBufLen = (512 * 8) + 4;
-
- TEndpoint* gEp = NULL;
- TEndpoint* gStatusEp = NULL;
- Boolean gConnectFlag = false;
- OSStatus gConnectErr = 0;
- Boolean gFlowControl = false;
- Boolean gDone = false;
- Boolean gEOF = false;
- char gReadBuf[kMaxSend];
- OTLIFO gEventList;
-
- UInt16 gStatSequence = 0;
- Boolean gStatusAvailable = false;
- Boolean gReceivedOrdRel = false;
- UInt8 gReplyBuffer[kMaxReplyBufLen];
- UInt8 gCurrentStatus[kMaxReplyBufLen]={0};
- UInt32 gNextStatusTime = 0;
- /*******************************************************************************
- ** Structures
- ********************************************************************************/
-
- class TOTEventItem
- {
- public:
- inline TOTEventItem(void* ref, unsigned long code,
- OTResult result, void* cookie)
- {
- fRef = ref;
- fCode = code;
- fResult = result;
- fCookie = cookie;
- };
- OTLink fLink;
- void* fRef;
- unsigned long fCode;
- OTResult fResult;
- void* fCookie;
- };
-
- /*******************************************************************************
- ** Prototypes
- ********************************************************************************/
-
- pascal void EventHandler(void*, OTEventCode, OTResult, void*);
- OTResult DoReceive(TEndpoint*, unsigned char*);
- OTResult DoRequestStatus(TEndpoint *ep, Boolean useName = false);
- void DoReadUReplies(TEndpoint*);
-
- /*******************************************************************************
- ** EventHandler
- ** The event handler can be called at times when it is not safe to do console I/O,
- ** so this routine takes the event and jams it on a list to be handled when
- ** we know it's safe to print informative messages
- ********************************************************************************/
-
- pascal void EventHandler(void* contextPtr, OTEventCode code,
- OTResult result, void* cookie)
- {
- TOTEventItem* item = new TOTEventItem(contextPtr, code, result, cookie);
-
- if (item == NULL)
- {
- DebugStr("\pPAPTest: UniversalEventHandler -- could not allocate event structure");
- }
- else
- {
- gEventList.Enqueue(&item->fLink);
- }
- }
-
-
-
- /*******************************************************************************
- ** PollEventList
- ** This routine picks up the events received by EventHandler and processes them
- ********************************************************************************/
-
- OSStatus PollEventList()
- {
- OSStatus err = kOTNoError;
- while ( true )
- {
- OTLink* link = OTReverseList(gEventList.StealList());
-
- if ( link == NULL )
- break;
-
- while ( link != NULL )
- {
- TOTEventItem* item = OTGetLinkObject(link, TOTEventItem, fLink);
-
- link = link->fNext;
-
- OTResult result = item->fResult;
- void* cookie = item->fCookie;
- int epNum = (int)item->fRef;
- if (epNum < 0 || epNum > 1)
- {
- fprintf(stderr, "PAPTest: PollEventList, Got bad refnum in event record");
- delete item;
- continue;
- }
-
- TEndpoint* ep = epNum ? gStatusEp : gEp;
-
- switch (item->fCode )
- {
-
- case T_DATA:
- {
- DoReceive(ep, gIncomingBuffer);
- fprintf(stderr, "Recieved Message: %s\n", gIncomingBuffer);
- break;
- }
-
- case T_CONNECT:
- {
- #if byName
- TCall rcvCall;
- rcvCall.addr.maxlen = sizeof gDestAddr;
- rcvCall.addr.buf = (UInt8*)&gDestAddr;
- rcvCall.opt.len = 0;
- rcvCall.udata.len = 0;
- OSStatus err = ep->RcvConnect(&rcvCall);
-
- gDestAddr.SetSocket(128); // set this to the SLS
- #endif
- #if byAddr
- OSStatus err = ep->RcvConnect(NULL);
- #endif
- if ( err != kOTNoError && err != kOTNoDataErr )
- {
- gConnectErr = err;
- DebugStr("\pPAPSample: RcvConnect returns an error!;g");
- }
- else
- gConnectFlag = true;
-
- break;
- }
-
- case T_GODATA:
- {
- gFlowControl = false; // indicate that flow control has lifted
- break;
- }
-
- case T_ORDREL:
- {
- err = ep->RcvOrderlyDisconnect();
- if ( err != kOTNoError )
- {
- DebugStr("\pRcvOrderlyDisconnect failed.;g");
- }
- gReceivedOrdRel = true;
- break;
- }
-
- case T_DISCONNECT:
- {
- TBind* bindReq = (TBind*)cookie;
- if ( bindReq != NULL ) // A connect is rejected
- {
- DebugStr("\pConnection attempt failed. Doing RcvDisconnect.;g");
- ep->RcvDisconnect(NULL);
- gConnectErr = -2; // special constant
- }
- break;
- }
-
- case T_REPLY :
- {
- DoReadUReplies(ep);
- break;
- }
-
-
- default:
- {
- DebugStr("\pPAPSample: Unexpected Event!;g");
- break;
- }
- }
- }
- }
- return err;
- }
-
- /*******************************************************************************
- ** DoBind
- ********************************************************************************/
-
- OSStatus DoBind(TEndpoint* ep, unsigned char socket, unsigned char type)
- {
- OSStatus err = kOTNoError;
-
- DDPAddress addr;
- addr.Init(0, 0, socket, type); // Source address & type
-
- TBind req;
- req.addr.buf = (UInt8*)&addr;
- req.addr.len = kDDPAddressLength;
- req.qlen = 0;
-
- TBind ret;
-
- ret.addr.buf = (UInt8*)&addr;
- ret.addr.maxlen = sizeof(addr);
-
- fprintf(stderr, "Doing Bind\n");
- //
- // Try to bind
- //
- err = ep->Bind(&req, &ret);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "PAPSample: DoBind returns error %d\n", err);
- return err;
- }
-
- fprintf(stderr, "Bound address = ");
- ShowDDPAddress(&addr);
- fprintf(stderr, "\n");
- fprintf(stderr, "Bound queue len is %d\n", ret.qlen);
-
- fprintf(stderr, "After Bind, ");
- ShowEndpointState(ep, "");
-
- return err;
- }
-
- /*******************************************************************************
- ** DoConnect
- ********************************************************************************/
-
- OSStatus DoConnect(TEndpoint* ep)
- {
- TCall theCall;
- #if byAddr
- theCall.addr.buf = (UInt8*)&gDestAddr;
- theCall.addr.len = kDDPAddressLength;
- #endif
- #if byName
- theCall.addr.buf = gDestName.buf;
- theCall.addr.len = gDestName.len;
- #endif
- theCall.opt.len = 0;
- theCall.udata.len = 0;
-
- OSStatus err = ep->Connect(&theCall, NULL);
- if ( err != kOTNoError && err != kOTNoDataErr )
- {
- fprintf(stderr, "Connect() returns %d\n", err);
- if ( err == kOTLookErr )
- {
-
- fprintf(stderr, "Calling RcvDisconnect()...");
- OSStatus err = ep->RcvDisconnect(NULL);
- fprintf(stderr, "returns %d\n", err);
- }
- }
- else
- {
- err = kOTNoError;
- Boolean flag = false;
- while ( !gConnectFlag && !gConnectErr && !(flag = Button()) )
- {
- OTIdle();
- PollEventList();
- }
-
- if ( flag )
- err = -1; //%%% for now
- else
- err = gConnectErr;
-
- }
- return err;
- }
-
- /*******************************************************************************
- ** DoRead
- ********************************************************************************/
-
- OSStatus DoReadData( FILE* fp, char **pp, size_t* countPtr)
- {
- if ( *countPtr == 0 )
- {
- size_t numread = fread(gReadBuf, 1, sizeof(gReadBuf), fp);
- if ( numread < 0 )
- {
- fprintf(stderr, "Error %s reading file\n", numread);
- return (OSStatus)numread;
- }
- gEOF = (numread < sizeof(gReadBuf));
- *countPtr = numread;
- *pp = gReadBuf;
- }
- }
-
-
- /*******************************************************************************
- ** DoSend
- ********************************************************************************/
-
- OSStatus DoSend(TEndpoint* ep, char **pp, size_t* countPtr)
- {
- if (*countPtr <= 0)DebugStr("\pBad Count!");
-
- if (gFlowControl || gDone)
- return 0;
-
-
- putc('.', stderr);
-
- OTResult result = ep->Snd(*pp, *countPtr, 0 );
-
- if ( result == kOTFlowErr )
- {
- fprintf(stderr, "Snd(%08X) flow controlled on NORMAL channel\n", ep);
- gFlowControl = true;
- return 1;
- }
-
- if ( result == kOTLookErr || result == kOTOutStateErr ||
- result == kEAGAINErr )
- return 1;
-
- if ( result < 0 )
- {
- fprintf(stderr, "Snd(%08X) fails with %d\n", ep, result);
- }
- else
- {
- (*countPtr) -= result;
- (*pp) += result;
- result = 0;
- }
-
- gDone = (gEOF && (*countPtr == 0));
-
- return (OSStatus)result;
- }
-
-
- /*******************************************************************************
- ** DoReceive
- ********************************************************************************/
-
- OTResult DoReceive(TEndpoint* ep, UInt8* buffer)
- {
- OTFlags flags = 0;
- OTResult result;
-
- while (true)
- {
-
- result = ep->Rcv(buffer, kMaxRecv, &flags);
- if ( result < 0 )
- {
- if ( result == kOTLookErr )
- {
- OTResult res = ep->Look();
- fprintf(stderr, "Rcv() returns LOOK, Look returns %d\n", res);
- if ( res == T_DATA )
- continue;
- }
- else if ( result != kOTNoDataErr )
- fprintf(stderr, "Rcv() returns %d\n", result);
- }
-
- return result;
- }
- }
- /*******************************************************************************
- ** DoReadUReplies
- ********************************************************************************/
-
- void DoReadUReplies(TEndpoint* atpEp)
- {
-
- OSStatus err;
- OTFlags flags;
-
- while ( true )
- {
- TUnitReply reply;
-
- reply.opt.maxlen = 0;
- reply.udata.maxlen = sizeof(gReplyBuffer);
- reply.udata.buf = gReplyBuffer;
-
- err = atpEp->RcvUReply(&reply, &flags);
-
- if ( err != kOTNoError )
- {
- if ( err == kOTNoDataErr )
- return;
- if ( err != kETIMEDOUTErr )
- {
- fprintf(stderr, "\nOTRcvUReply: returned error %d\n", err);
- return;
- }
- }
-
- // If this is really the reply to our last request, save it.
- if ( reply.sequence == gStatSequence )
- {
- gStatusAvailable = true;
- if (!EqualString(gCurrentStatus, gReplyBuffer+8, true, true) )
- {
- fprintf(stderr, "\n>> %#s\n", gReplyBuffer+8);
- memcpy(gCurrentStatus, gReplyBuffer+8, reply.udata.len);
- }
- }
-
- }
- }
-
- /*******************************************************************************
- ** CreatePAPEndpoint
- ********************************************************************************/
-
- TEndpoint* CreatePAPEndpoint()
- {
- TEndpoint* ep = NULL;
- OSStatus err = kOTNoError;
-
- do
- {
- //
- // Create a PAP
- //
- ep = OTOpenEndpoint(OTCreateConfiguration(kPAPName), 0, NULL, &err);
-
- if ( ep == NULL || err != kOTNoError )
- {
- ep = NULL;
- fprintf(stderr,"ERROR: OpenEndpoint(\"pap\") failed with %d\n", err);
- break;
- }
- ep->SetSynchronous();
-
- //
- // Install notifier we're going to use for testing
- //
- err = ep->InstallNotifier(EventHandler, NULL);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: InstallNotifier() failed with %d\n", err);
- break;
- }
-
- ShowFullEndpointData(ep);
-
- return ep;
-
- } while ( false );
-
- if ( ep != NULL )
- ep->Close();
-
- return NULL;
- }
-
- /*******************************************************************************
- ** CreateATPEndpoint
- ** Note that this will be a synchronous endpoint, so we don't need a notifier.
- ********************************************************************************/
-
- TEndpoint* CreateATPEndpoint()
- {
- TEndpoint* ep = NULL;
- OSStatus err = kOTNoError;
-
- do
- {
- //
- // Create a PAP
- //
- ep = OTOpenEndpoint(OTCreateConfiguration(kATPName), 0, NULL, &err);
-
- if ( ep == NULL || err != kOTNoError )
- {
- ep = NULL;
- fprintf(stderr,"ERROR: OpenEndpoint(\"atp\") failed with %d\n", err);
- break;
- }
- ep->SetSynchronous();
-
- //
- // Install notifier we're going to use for testing
- //
- err = ep->InstallNotifier(EventHandler, (void*)1);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: InstallNotifier() failed with %d\n", err);
- break;
- }
-
-
- return ep;
-
- } while ( false );
-
- if ( ep != NULL )
- ep->Close();
-
- return NULL;
- }
-
- /*******************************************************************************
- ** DoRequestStatus
- ********************************************************************************/
- OTResult DoRequestStatus(TEndpoint *ep, Boolean useName)
- {
- static UInt8 requestMsg[4] = {0, 8, 0, 0};
-
- TUnitRequest theReq;
-
- if ( useName )
- {
- theReq.addr.buf = gDestName.buf;
- theReq.addr.len = gDestName.len;
- }
- else
- {
- theReq.addr.buf = (UInt8*)&gDestAddr;
- theReq.addr.len = kDDPAddressLength;
- }
- theReq.opt.len = 0;
- theReq.udata.buf = requestMsg;
- theReq.udata.len = sizeof requestMsg;
-
- theReq.sequence = ++gStatSequence;
-
- gStatusAvailable = false;
-
- OTResult err = ep->SndURequest(&theReq, 0);
-
- gNextStatusTime = TickCount()+60;
-
- if ( err != kOTNoError )
- fprintf(stderr, "SndURequest returns %d\n", err);
-
- return err;
- }
-
-
- /*******************************************************************************
- ** DoTest
- ********************************************************************************/
-
- void DoTest()
- {
- OSStatus err = kOTNoError;
-
- FILE *fp=NULL;
-
- do
- {
- /* -------------------------------------------------------------------------
- Create endpoint.
- ------------------------------------------------------------------------- */
-
- gEp = CreatePAPEndpoint();
- if ( gEp == NULL )
- {
- fprintf(stderr, "PAPSample: CreatePAPEndpoint for endpoint failed.\n", err);
- break;
- }
-
- /*-------------------------------------------------------------------------
- Bind endpoint.
- ------------------------------------------------------------------------- */
-
- UInt8 socket = 48;
- UInt8 type = 3;
-
- err = DoBind(gEp, socket, type);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "PAPSample: bind of PAP endpoint #1 failed.\n");
- break;
- }
-
- gEp->SetAsynchronous();
-
- /* -------------------------------------------------------------------------
- In order to get status from the printer, we have to use ATP. So let's open
- and ATP endpoint.
- ------------------------------------------------------------------------- */
-
- gStatusEp = CreateATPEndpoint();
- if ( gStatusEp == NULL )
- {
- fprintf(stderr, "PAPSample: CreateATPEndpoint for endpoint failed .\n", err);
- break;
- }
-
- /*-------------------------------------------------------------------------
- Bind status endpoint.
- ------------------------------------------------------------------------- */
-
- socket = 0;
- type = 3;
-
- err = DoBind(gStatusEp, socket, type);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "PAPSample: bind of ATP endpoint #1 failed.\n");
- break;
- }
-
- gEp->SetAsynchronous();
-
- /* -------------------------------------------------------------------------
- Run the test.
- ------------------------------------------------------------------------- */
- do
- {
- char fileName[256];
- fprintf(stderr, "Enter name of input file:\n");
- while ( true )
- {
- gets(fileName);
- if ( fileName[0] != 0 )
- break;
- }
-
- fp = fopen(fileName, "r");
- if (fp == NULL)
- {
- fprintf(stderr, "Couldn't open file %s\n", fileName);
- break;
- }
-
- #if byName
- NBPAddress addr;
- char addrBuf[64];
-
- fprintf(stderr, "Enter name to send to in form 'name:type@zone'\n");
- while ( true )
- {
- gets(addrBuf);
- if ( addrBuf[0] != 0 )
- break;
- }
- gDestName.buf = (UInt8*)&addr;
- gDestName.len = addr.Init(addrBuf);
- #endif
- #if byAddr
- int net, node, socket;
-
- fprintf(stderr, "Enter the target network: ");
- scanf("%x", &net);
- fprintf(stderr, "Enter the target node: ");
- scanf("%x", &node);
- fprintf(stderr, "Enter the target socket: ");
- scanf("%x", &socket);
-
- gDestAddr.Init((UInt16)net, (UInt8)node, (UInt8)socket);
- fprintf(stderr, "Target net node socket: %.4x %.2x %.2x \n",net, node, socket);
- #endif
- //
- // See what our status looks like
- //
- DoRequestStatus(gStatusEp, true);
- //
- // Connect
- //
- err = DoConnect(gEp);
- if ( err != kOTNoError )
- {
- if ( err == -2 )
- fprintf(stderr, "Connection attempt failed\n");
- else
- fprintf(stderr, "DoConnect returned %d\n", err);
- break;
- }
- //
- // See what our status looks like
- //
- DoRequestStatus(gStatusEp);
-
-
- //
- // Try to Send some data
- //
- fprintf(stderr, "Copying File:\n");
-
- gFlowControl = false;
- gDone = false;
-
- size_t count = 0;
- char *bufPtr = NULL;
-
- do
- {
- err = DoReadData(fp, &bufPtr, &count);
- if ( err < 0 )
- break;
-
- err = DoSend(gEp, &bufPtr, &count);
- if ( err < 0 )
- break;
-
- OTIdle();
- if (TickCount() >= gNextStatusTime)
- DoRequestStatus(gStatusEp);
- PollEventList();
-
- } while ( !gDone );
- fprintf(stderr, "Write Complete\n");
-
- } while ( false );
-
- if ( gConnectFlag )
- {
- fprintf(stderr, "Press mouse to disconnect\n");
- while ( !Button() ) // Wait for mouse button
- {
- OTIdle();
- if (TickCount() >= gNextStatusTime)
- DoRequestStatus(gStatusEp);
- PollEventList();
- }
- while ( Button() ) // Wait 'til it's released
- {
- OTIdle();
- if (TickCount() >= gNextStatusTime)
- DoRequestStatus(gStatusEp);
- PollEventList();
- }
-
- //
- // Send Orderly Release
- //
- gEp->SetSynchronous();
- fprintf(stderr, "About to Disconnect()\n");
- gReceivedOrdRel = false;
- err = gEp->SndOrderlyDisconnect();
- if ( err != kOTNoError )
- {
- if ( err == kOTLookErr )
- {
- fprintf(stderr,
- "SndOrderlyDisconnect(%d) returns with kLook\n", gEp);
- err = 0;
- }
- else
- fprintf(stderr,
- "SndOrderlyDisconnect(%d) fails with %d\n", gEp, err);
- }
-
- while( !gReceivedOrdRel && !Button() )
- {
- OTIdle();
- if (TickCount() >= gNextStatusTime)
- DoRequestStatus(gStatusEp);
- PollEventList();
- }
- ShowEndpointState(gEp, "");
- }
-
-
- //
- // Unbind
- //
- fprintf(stderr, "About to Unbind()\n");
- err = gEp->Unbind();
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: Unbind(pap) returned %d\n", err);
- break;
- }
- ShowEndpointState(gEp, "");
-
- err = gStatusEp->Unbind();
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: Unbind(atp) returned %d\n", err);
- break;
- }
- ShowEndpointState(gStatusEp, "");
-
- } while (false);
-
- //
- // Get rid of endpoint.
- //
- if ( gStatusEp != NULL )
- {
- gStatusEp->RemoveNotifier();
- gStatusEp->Close();
- } //
- // Get rid of endpoint.
- //
- if ( gStatusEp != NULL )
- {
- gStatusEp->RemoveNotifier();
- gStatusEp->Close();
- }
-
- //
- // close our file
- //
- if ( fp != NULL )
- fclose(fp);
-
- }
-
- /*******************************************************************************
- ** Initialize OpenTransport and call DoTest function
- ********************************************************************************/
-
- main(int, char**)
- {
- InitGraf(&qd.thePort); // initialize quickdraw so we can use regions
-
- fprintf(stderr, "PAPSample showing usage of PAP.\n\n");
- //
- // Initialize Open Transport
- //
- InitOpenTransport();
- //
- // Run the test
- //
- DoTest();
- //
- // Close Open Transport.
- // Not strictly necessary since it patches _ExitToShell and will
- // clean us up anyway.
- //
- CloseOpenTransport();
-
- fprintf(stderr, "\n\nDone\n");
-
- return 0;
- };
-
-